package com.mazecore.game;

import java.util.Random;

public class MazeGenerator {

    private int[] maze;
    private int cycle;
    private int width = 0;
    private int height = 0;
    private int length = 0;
    private Random random = new Random();

    public int[] getMaze() {
        return maze;
    }

    public MazeGenerator(int width, int height, int length) {
        this.width = width;
        this.height = height;
        this.length = length;
    }
    int x = 0;

    public void generateWalls() {
        int size = (++width) * (++height);
        maze = new int[size];
        createborder();
        createdoors();
        

        int z = 0;
        x = 0;
        cycle += size + size / 2;
        while (getrandom() > 0) {
            if (maze[x] == 1) {
                continue;
            }
            z = getdirection();
            do {
                if (maze[x] == 0) {
                    maze[x] = 1;
                }
                x += z;
                if (random.nextInt(100) > length) {
                    break;
                }
            } while (maze[x] == 0);
        }
        createpos();
    }

    protected void createborder() {
        for (int i = 0; i < (width * height); i++) {
            if (i < width || i % width == 0 || i % width == width - 1 || i > width * (height - 1)) {
                maze[i] = 1;
            }
        }
    }

    protected void createdoors() {
        int t;
        do {
            t = oddbetween(0, width);
        } while (t == 0 || t == width);
        maze[t] = 0x2F;
    }
    
    protected void createpos() {
        for(int i=(width * (height-1) - 1); i>=width; i--) {
            if(i%width != 0 && i%width != width-1) {
                if(maze[i] == 0) {
                    if((maze[i+1] == 0 && maze[i-1] == 1 &&
                        maze[i+width] == 1 && maze[i-width] == 1) ||
                       (maze[i+1] == 1 && maze[i-1] == 0 &&
                        maze[i+width] == 1 && maze[i-width] == 1) ||
                       (maze[i+1] == 1 && maze[i-1] == 1 &&
                        maze[i+width] == 0 && maze[i-width] == 1) ||
                       (maze[i+1] == 1 && maze[i-1] == 1 &&
                        maze[i+width] == 1 && maze[i-width] == 0))
                            maze[i] = 2;
                }
            }
        }
    }

    protected int getdirection() {
        int z = random.nextInt(4);
        return (z == 0 ? -1 : z == 1 ? 1 : z == 2 ? width : -width);
    }

    protected int oddbetween(int n1, int n2) {
        int t;
        return (t = myoddrand(n2)) > n1 ? t : oddbetween(n1, n2);
    }

    protected int evenbetween(int n1, int n2) {
        int t;
        return (t = myevenrand(n2)) > n1 ? t : evenbetween(n1, n2);
    }

    protected int getrandom() {
        int row, col;
        row = evenbetween(0, height);
        col = evenbetween(0, width);
        x = width * row + col;
        if ((x % width) % 2 != 0) {
            getrandom();
        }
        return cycle--;
    }

    void display() {
        int row = 0;
        char ch = 32;
        for(int i = 0; i < height * width; i++)
        {
            System.out.println(i + ") " + maze[i]);
        }
        for (int i = 0; i < height * width; i++) {
            if (i % width == 0) {
                System.out.printf("\n");
            }
            if(maze[i] == 1) ch = 'X';
            else if(maze[i] == 2) ch = 'O';
            else ch = 32;
            System.out.printf("%c", ch);
            row++;
        }
    }

    private int myevenrand(int _num) {
        return (random.nextInt(_num) & 0xFE);
    }

    private int myoddrand(int _num) {
        return (random.nextInt(_num) | 0x01);
    }
}
